/*
# PostgreSQL Database Modeler (pgModeler)
#
# Copyright 2006-2025 - Raphael Araújo e Silva <raphael@pgmodeler.io>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# The complete text of GPLv3 is at LICENSE file on source code root directory.
# Also, you can get the complete GNU General Public License at <http://www.gnu.org/licenses/>
*/

/**
\ingroup libcore
\class Column
\brief Implements basic operations to manipulate table columns.
\note <strong>Creation date:</strong> 12/09/2006
*/

#ifndef COLUMN_H
#define COLUMN_H

#include "tableobject.h"
#include "pgsqltypes/pgsqltype.h"
#include "pgsqltypes/identitytype.h"

class __libcore Column: public TableObject{
	protected:
		/*! \brief Stores the previous name of the column before its name has changed.
		 This attribute assists in the process of reference columns added
		 by relationships. */
		QString old_name;

		//! \brief Indicates that the column accepts null values or not
		bool not_null;

		//! \brief Indicates that the column is a generated one (PostgreSQL 12+)
		bool generated;

		//! \brief Data type of the column
		PgSqlType type;

		/*! \brief Default value of the column.
		 Note: The user must format the default value in
					 accordance with the requirements for each data type.
					 E.g.: for a varchar(10) default value should be 'abcdef' (including apostrophe)
					 for a date the defaul value should be '2006-09-12 ' and so on. */
		QString default_value;

		/*! \brief Stores a reference to the sequence used to generate the default value.
		 * This attribute is used only the data type is integer, smallint or bigint */
		BaseObject *sequence;

		//! \brief Identity type of the column (GENERATED BY DEFAULT | ALWAYS)
		IdentityType identity_type;

		/*! \brief Indicates that the underlying sequence is cyclic
		 (the counter resets when maximum value is reached) (only for identity column) */
		bool seq_cycle;

		//! \brief Underlying sequence's minimum value (only for identity column)
		QString seq_min_value,

		//! \brief Underlying sequence's maximum value (only for identity column)
		seq_max_value,

		//! \brief Underlying sequence's current sequence value (only for identity column)
		seq_start,

		//! \brief Underlying sequence's value increment (only for identity column)
		seq_increment,

		//! \brief Underlying sequence's cache value (only for identity column)
		seq_cache;

		void configureSearchAttributes() override;

	public:
		//! \brief Holds the pattern for nextval() function call
		static const QString NextValFuncTmpl;

		Column();
		~Column() override = default;

		//! \brief Defines if the column accepts null values or not
		void setNotNull(bool value);

		//! \brief Defines wether the column is generated from the computation of the values of other columns (PostgreSQL 12+)
		void setGenerated(bool value);

		//! \brief Defines the column data type
		void setType(PgSqlType tp);

		//! \brief Defines the identity mode of the column
		void setIdentityType(IdentityType id_type);

		/*! \brief Sets the default value of the column. Must be informed together with the value
		 the particularities of each type, such as quotation marks, hyphens, etc. */
		void setDefaultValue(const QString &value);

		/*! \brief Defines the column name. This method keeps the last column name
		 stored to assist the objects like constraints / indixes and sequences
		 that is referencing the column by its old name. */
		void setName(const QString &name) override;

		//! \brief Returns the not null state of the column
		bool isNotNull();

		//! \brief Returns the generated of the column
		bool isGenerated();

		//! \brief Returns wheter the column is identity or not (GENERATED BY DEFAULT | ALWAYS)
		bool isIdentity();

		//! \brief Returns the data type of the column
		PgSqlType getType();

		//! \brief Returns the identity mode of the column
		IdentityType getIdentityType();

		//! \brief Returns the default value of the column
		QString getDefaultValue();

		//! \brief Returns the SQL/XML code definition for the column
		QString getSourceCode(SchemaParser::CodeType def_type) override;

		QString getAlterCode(BaseObject *object) override;

		/*! \brief Returns the old column name. The parameter 'format' indicates
		 whether the name must be formatted or not */
		QString getOldName(bool format=false);

		//! \brief Returns the reference to the column type in the form [schema].table.column_name%TYPE
		QString getTypeReference();

		//! \brief Set the sequence that will generate the default value for the column
		void setSequence(BaseObject *seq);

		//! \brief Returns the sequence generator of default value
		BaseObject *getSequence();

		//! \brief Sets at once all the necessary fields to define the underlying sequence's attributes
		void setIdSeqAttributes(QString minv, QString maxv, QString inc, QString start, QString cache, bool cycle);

		bool isIdSeqCycle();
		QString getIdSeqMaxValue();
		QString getIdSeqMinValue();
		QString getIdSeqIncrement();
		QString getIdSeqStart();
		QString getIdSeqCache();

		//! \brief Copies on column to other
		void operator = (Column &col);

		QString getDataDictionary(bool md_format, const attribs_map &extra_attribs = {});

		void updateDependencies() override;

		void generateHashCode() override;
};

#endif
